package org.springblade.tms.global.utils;


import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import lombok.SneakyThrows;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.spec.*;


import org.apache.xmlbeans.impl.util.Base64;

/**
 * @projectName: BladeX
 * @package: org.springblade.tms.global.utils
 * @className: RSAUtils
 * @author: yr
 * @description: RSA加密算法Utils
 * @date: 2022/5/13 17:45
 */
public class RSAUtils {
	/**
	 * RSA最大加密明文大小
	 */
	private static final int MAX_ENCRYPT_BLOCK = 117;
	/**
	 * RSA最大解密密文大小
	 */
	private static final int MAX_DECRYPT_BLOCK = 128;
	/**
	 * 加密算法RSA
	 */
	private static final String KEY_ALGORITHM = "RSA";
	/**
	 * 字符编码集
	 */
	public static final String CHARSET = "utf-8";
	/**
	 * 签名方式
	 */
	public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

	/**
	 * 公钥加密
	 *
	 * @param data
	 * @return
	 * @throws Exception
	 */
	@SneakyThrows
	public static String encryptByPublicKey(String data, String Key) {
		//data = "4E6684C720B251FB";
		byte[] dataByte = data.getBytes();
		byte[] keyBytes = Base64Utils.decode(Key);
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key publicK = keyFactory.generatePublic(x509KeySpec);
		// 对数据加密
		// Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(Cipher.ENCRYPT_MODE, publicK);
		int inputLen = dataByte.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段加密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
				cache = cipher.doFinal(dataByte, offSet, MAX_ENCRYPT_BLOCK);
			} else {
				cache = cipher.doFinal(dataByte, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_ENCRYPT_BLOCK;
		}
		byte[] encryptedData = out.toByteArray();
		out.close();
		return Base64Utils.encode(encryptedData);
	}

	/**
	 * 私钥加密
	 *
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static String ucEncryptByPrivateKey(String data, String privateKey) throws Exception {
		byte[] dataByte = data.getBytes();
		byte[] keyBytes = Base64Utils.decode(privateKey);
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key publicK = keyFactory.generatePrivate(pkcs8KeySpec);
		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(Cipher.ENCRYPT_MODE, publicK);
		int inputLen = dataByte.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段加密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
				cache = cipher.doFinal(dataByte, offSet, MAX_ENCRYPT_BLOCK);
			} else {
				cache = cipher.doFinal(dataByte, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_ENCRYPT_BLOCK;
		}
		byte[] encryptedData = out.toByteArray();
		out.close();
		return Base64Utils.encode(encryptedData);
	}

	/**
	 * @param base64DecodeStr:
	 * @param privateKey:
	 * @return String
	 * @author yr
	 * @description kafka私钥解密
	 * @date 2022/5/18 16:48
	 */
	public static String decrypt(String base64DecodeStr, String privateKey) throws Exception {
		try {
			RSA rsa1 = new RSA(privateKey, null);
			byte[] decode = Base64.decode(base64DecodeStr.getBytes());
			byte[] decrypt = rsa1.decrypt(decode, KeyType.PrivateKey);
			return StrUtil.utf8Str(decrypt);
		} catch (Exception e) {
			throw new Exception("密码解密失败!");
		}
	}

}
